/**
 * 解决js计算精度不准
 * */
import { create, all } from "mathjs";
const config = {
  number: "BigNumber",
  precision: 20, // 精度
};
const math = create(all, config);
//加
export const numberAdd = (arg1, arg2) => {
  return math.number(math.add(math.bignumber(arg1), math.bignumber(arg2)));
};
//减
export const numberSub = (arg1, arg2) => {
  return math.number(math.subtract(math.bignumber(arg1), math.bignumber(arg2)));
};
//乘
export const numberMultiply = (arg1, arg2) => {
  return math.number(math.multiply(math.bignumber(arg1), math.bignumber(arg2)));
};
//除
export const numberDivide = (arg1, arg2) => {
  return math.number(math.divide(math.bignumber(arg1), math.bignumber(arg2)));
};

// 数组样本标准差公式  OK
export const stdDeviation = (arr) => {
  return Math.sqrt(varianceArr(arr));
};

// 数组总体标准差公式  OK
export const popVariance = (arr) => {
  return Math.sqrt(popStandardDeviation(arr));
};

// 数组总体方差公式   OK
export const popStandardDeviation = (arr) => {
  let s,
    ave,
    sum = 0,
    sums = 0,
    len = arr.length;
  for (let i = 0; i < len; i++) {
    sum = numberAdd(Number(arr[i]), sum);
  }
  ave = numberDivide(sum, len);
  for (let i = 0; i < len; i++) {
    sums = numberAdd(
      sums,
      numberMultiply(
        numberSub(Number(arr[i]), ave),
        numberSub(Number(arr[i]), ave)
      )
    );
  }
  s = numberDivide(sums, len);
  return s;
};

// 数组加权公式   OK
export const weightedAverage = (arr1, arr2) => {
  // arr1: 计算列，arr2: 选择的权重列
  let s,
    sum = 0, // 分子的值
    sums = 0, // 分母的值
    len = arr1.length;
  for (let i = 0; i < len; i++) {
    sum = numberAdd(numberMultiply(Number(arr1[i]), Number(arr2[i])), sum);
    sums = numberAdd(Number(arr2[i]), sums);
  }
  s = numberDivide(sum, sums);
  return s;
};

// 数组样本方差公式  OK
export const varianceArr = (arr) => {
  let s,
    ave,
    sum = 0,
    sums = 0,
    len = arr.length;
  for (let i = 0; i < len; i++) {
    sum = numberAdd(Number(arr[i]), sum);
  }
  ave = numberDivide(sum, len);
  for (let i = 0; i < len; i++) {
    sums = numberAdd(
      sums,
      numberMultiply(
        numberSub(Number(arr[i]), ave),
        numberSub(Number(arr[i]), ave)
      )
    );
  }
  s = numberDivide(sums, len - 1);
  return s;
};

// 数组中位数  OK
export const middleNum = (arr) => {
  arr.sort((a, b) => a - b);
  // if (arr.length === 0) return '-'
  if (arr.length % 2 === 0) {
    //判断数字个数是奇数还是偶数
    return numberDivide(
      numberAdd(arr[arr.length / 2 - 1], arr[arr.length / 2]),
      2
    ); //偶数个取中间两个数的平均数
  } else {
    return arr[(arr.length + 1) / 2 - 1]; //奇数个取最中间那个数
  }
};

// 数组求和  OK
export const sum = (arr) => {
  let sum = 0,
    len = arr.length;
  for (let i = 0; i < len; i++) {
    sum = numberAdd(Number(arr[i]), sum);
  }
  return sum;
};

// 数组平均值  OK
export const average = (arr) => {
  return numberDivide(sum(arr), arr.length);
};

// 数组最大值 OK
export const max = (arr) => {
  return Math.max(...arr);
};

// 数组最小值 OK
export const min = (arr) => {
  return Math.min(...arr);
};

export const arrayMin = (arr) => {
  const newList = arr.filter((item) => {
    return item || item === 0;
  });
  newList.sort((pre, cur) => {
    return pre - cur;
  });
  return newList?.[0];
};
export const arrayMax = (arr) => {
  const newList = arr.filter((item) => {
    return item || item === 0;
  });
  newList.sort((pre, cur) => {
    return cur - pre;
  });
  return newList?.[0];
};
// 数组有效数据长度
export const count = (arr) => {
  let remove = ["", " ", null, undefined, "-"];
  return arr.filter((item) => !remove.includes(item)).length;
};

// 数字三位加逗号，保留两位小数
export const formatNumber = (num) => {
  if (!num || num == "-") return "--";
  num = typeof num == "string" ? parseFloat(num) : num;
  return num.toFixed(2).replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, "$&,");
};

// 数字三位加逗号，动态保留小数位数
export const formatPoint = (num, pointNum = 2) => {
  if ((!num && num !== 0) || num == "-") return "--";
  let arr = (typeof num == "string" ? parseFloat(num) : num)
    .toFixed(pointNum)
    .split(".");
  let intNum = arr[0].replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, "$&,");
  const res = `${intNum}.${arr[1]}`;
  //-0处理为0
  return arr[1] === undefined ? intNum : res == 0 ? `0.${arr[1]}` : res;
};

// 数字三位加逗号，动态保留小数位数-适用于 数字三位
export const formatPointPro = (num, pointNum = 2) => {
  if ((!num && num !== 0) || num == "-") return "--";
  let arr = (
    typeof num == "string" ? parseFloat(String(num).split(",").join("")) : num
  )
    .toFixed(pointNum)
    .split(".");
  let intNum = arr[0].replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, "$&,");
  return arr[1] === undefined ? intNum : `${intNum}.${arr[1]}`;
};

// 动态保留小数位数
export const formatDecimal = (num, n) => {
  let numh = String(num).split(",").join("");
  return parseFloat(numh).toFixed(n);
};

// 小数点保留n位有效数字
export const formatToFixed = (num, n) => {
  return Number(Number(num).toFixed(n));
};

// 科学计数法
export const scientific = (num, n) => {
  let numh = typeof num == "string" ? parseFloat(num) : num;
  let p = Math.floor(Math.log(numh) / Math.LN10);
  let m = (numh * Math.pow(10, -p)).toFixed(n);
  p = p >= 10 ? `+${p}` : p >= 0 ? `+0${p}` : p > -10 ? `-0${-p}` : `-${-p}`;
  return m + "E" + p;
};
